ES6 中强大实用的语法有很多,例如:let关键字,const关键字,变量的解构赋值,模板字符串,简化对象,箭头函数,”…”拓展运算符,形参默认值,Promise 对象,Symbol 类型,Iterator 遍历器,Generator 函数,Async 函数,Class 等等。
前面说了 ES6 中的 Promise,今天来看看 Symbol,Iterator,Generator,Async,Class:
Symbol
ES5 中对象的属性名都是字符串,容易造成重名,污染环境,所以有了现在的 symbol~
概念:ES6 中的添加了一种原始数据类型 symbol (已有的原始数据类型:String, Number, boolean, null, undefined, 对象)
特点:
- Symbol 属性对应的值是唯一的,解决命名冲突问题
- Symbol 值不能与其他数据进行计算,包括同字符串拼串
- for in, for of遍历时不会遍历symbol属性。
使用方式:
- 调用Symbol函数得到symbol值:
1 | let symbol = Symbol(); |
- 传参标识
1 | let symbol = Symbol('one'); |
- 内置Symbol值:除了定义自己使用的 Symbol 值以外,ES6 还提供了11个内置的 Symbol 值,指向语言内部使用的方法,其中最重要最常用的为:
Symbol.iterator
,对象的 Symbol.iterator 属性,指向该对象的默认遍历器方法。
使用案例:
1 | let symbol = Symbol(); |
Iterator 遍历器
概念: iterator 是一种接口机制,为各种不同的数据结构提供统一的访问机制。
作用:
- 为各种数据结构,提供一个统一的、简便的访问接口;
- 使得数据结构的成员能够按某种次序排列
- ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费。
工作原理:
- 创建一个指针对象,指向数据结构的起始位置。
- 第一次调用 next 方法,指针自动指向数据结构的第一个成员
- 接下来不断调用 next 方法,指针会一直往后移动,直到指向最后一个成员
- 每调用next方法返回的是一个包含 value 和 done 的对象,{value: 当前成员的值,done: 布尔值},其中,value表示当前成员的值,done 对应的布尔值表示当前的数据的结构是否遍历结束。并且当遍历结束的时候返回的 value 值是 undefined,done值为 true。
原生具备iterator接口的数据(可用for of遍历)有:Array、arguments、set容器、map容器、String等等。
使用方式:
自定义 iterator 生成指针对象:
1 | function mockIterator(arr) { |
使用解构赋值以及…三点运算符时会调用iterator接口
1 | let arr1 = [1,2,3,4,5]; |
yield*语句:
1 | function* generatorObj() { |
原生数组:
1 | let arr3 = [1, 2, 'kobe', true]; |
字符串:
1 | let str = 'abcdefg'; |
Generator 函数
概念:
- ES6 提供的解决异步编程的方案之一(Promise对象,Generator函数,Async函数)
- Generator 函数是一个状态机,内部封装了不同状态的数据
- 用来生成遍历器对象
- 可暂停函数(惰性求值), yield 可暂停,next 方法可启动。每次返回的是 yield 后的表达式结果
特点:
- function 与函数名之间有一个星号
- 内部用 yield 表达式来定义不同的状态
- generator 函数返回的是指针对象(利用 iterator 遍历器),而不会执行函数内部逻辑
- 调用 next 方法函数内部逻辑开始执行,遇到 yield 表达式停止,返回 {value: yield后的表达式结果/undefined, done: false/true}
- 再次调用next方法会从上一次停止时的yield处开始,直到最后
- yield 语句返回结果通常为 undefined, 当调用 next 方法时传参内容会作为启动时 yield 语句的返回值。
使用方式:
1 | //内部用 yield 表达式来定义不同的状态 |
1 | function* generatorTest() { |
1 | // 用对象的 Symbol.iterator 属性,指向遍历器对象,使对象可用 for of 遍历 |
使用案例:
1 | * 需求: |
上面是 Generator 函数版(引入jquery),下面我们对比一下上次的 Promise 版(原生js):
1 | //定义一个请求news的方法 |
接下来我们还有 Async 版(引入jquery):
1 | async function sendXml(url) { |
Async 函数(源自ES2017)
概念: 真正意义上去解决异步回调的问题,同步流程表达异步操作。本质是 Generator 的语法糖
语法:
1 | async function foo(){ |
特点:
- 不需要像 Generator 去调用 next 方法,遇到 await 等待,当前的异步操作完成就往下执行
- 返回的总是 Promise 对象,可以用 then 方法进行下一步操作
- async 取代 Generator 函数的星号*,await 取代 Generator 的 yield
- 语意上更为明确,使用简单,经临床验证,暂时没有任何副作用
可以说,Async 函数是结合了 Promise 和 Generator 函数的使用。
使用方式:
1 | //定义 async 函数 |
关于 Async 返回值:
普通函数返回的就是普通函数的返回值:
1 | function test() { |
Async 函数:
1 | async function test() { |
Promise 需要把结果放在 resolve 里面而不是 return。
用 Class 定义类
在《你不知道的javascript》中有对 class 作如下解释:
你可能会认为 ES6 的class 语法是向 JavaScript 中引入了一种新的“类”机制,其实不是这样。class 基本上只是现有[[Prototype]](委托!)机制的一种语法糖。
也就是说,class 并不会像传统面向类的语言一样在声明时静态复制所有行为。如果你(有意或无意)修改或者替换了父“类”中的一个方法,那子“类”和所有实例都会受到影响,因为它们在定义时并没有进行复制,只是使用基于[[Prototype]] 的实时委托:
1 | class C { |
使用步骤:
- 通过class定义类/实现类的继承
- 在类中通过constructor定义构造方法
- 通过new来创建类的实例
- 通过extends来实现类的继承
- 通过super调用父类的构造方法
- 重写从父类中继承的一般方法
使用方式:
1 | class Person { |
完~